package com.connector.base.connection.impl;

import com.connector.base.connection.Connection;
import com.connector.base.connection.ConnectionRegistry;
import com.connector.base.connection.channel.SocketChannel;
import com.connector.base.exception.ServiceException;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

public class LocalConnectionRegistry implements ConnectionRegistry
{
    private static final Logger log;
    private static ConcurrentMap<SocketChannel, Connection> CONNECTIONS;
    private AtomicInteger status;

    public LocalConnectionRegistry() {
        this.status = new AtomicInteger(0);
    }

    @Override
    public Connection get(final SocketChannel socketClient) {
        return LocalConnectionRegistry.CONNECTIONS.get(socketClient);
    }

    @Override
    public Connection removeAndClose(final SocketChannel socketClient) {
        return LocalConnectionRegistry.CONNECTIONS.remove(socketClient);
    }

    @Override
    public void add(final Connection connection) {
        LocalConnectionRegistry.CONNECTIONS.putIfAbsent(connection.getSocketClient(), connection);
    }

    @Override
    public int getConnectionNum() {
        return LocalConnectionRegistry.CONNECTIONS.size();
    }

    @Override
    public void init() {
        if (!this.status.compareAndSet(0, 1)) {
            throw new ServiceException("connection registry init failure");
        }
    }

    @Override
    public void destroy() {
        if (!this.status.compareAndSet(1, 2)) {
            throw new ServiceException("connection registry destroy failure");
        }
        LocalConnectionRegistry.CONNECTIONS.values().forEach(Connection::disConnect);
        LocalConnectionRegistry.CONNECTIONS.clear();
    }

    public static List<Connection> getPrivateConnection(final String userId) {
        final List<Connection> connections = Lists.newArrayList();
        for (final Connection c : LocalConnectionRegistry.CONNECTIONS.values()) {
            final NettyConnection conn = (NettyConnection)c;
            if (userId.equals(conn.getUserId())) {
                connections.add(conn);
            }
        }
        return connections;
    }

    public static ConcurrentMap<SocketChannel, Connection> getConnections() {
        return LocalConnectionRegistry.CONNECTIONS;
    }

    static {
        log = LoggerFactory.getLogger((Class) LocalConnectionRegistry.class);
        LocalConnectionRegistry.CONNECTIONS = new ConcurrentHashMap<SocketChannel, Connection>();
    }
}
